home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 25 / AACD 25.iso / AACD / Magazine / Online / QMail / source / qmail-popup.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-15  |  4.7 KB  |  220 lines

  1. #include <sys/types.h>
  2. #include <sys/stat.h>
  3. #include "fd.h"
  4. #include "sig.h"
  5. #include "getln.h"
  6. #include "stralloc.h"
  7. #include "substdio.h"
  8. #include "subfd.h"
  9. #include "alloc.h"
  10. #include "datetime.h"
  11. #include "error.h"
  12. #include "wait.h"
  13. #include "str.h"
  14. #include "now.h"
  15. #include "fmt.h"
  16. #include "exit.h"
  17. #include "readwrite.h"
  18.  
  19. int timeout = 1200;
  20.  
  21. int timeoutread(fd,buf,n) int fd; char *buf; int n;
  22. {
  23.  int r; int saveerrno;
  24.  alarm(timeout);
  25.  r = read(fd,buf,n); saveerrno = errno;
  26.  alarm(0);
  27.  errno = saveerrno; return r;
  28. }
  29.  
  30. char ssinbuf[128];
  31. substdio ssin = SUBSTDIO_FDBUF(timeoutread,0,ssinbuf,sizeof(ssinbuf));
  32.  
  33.  
  34. void die() { _exit(1); }
  35. void out(s) char *s;
  36. {
  37.  if (substdio_puts(subfdoutsmall,s) == -1) die();
  38. }
  39. void outflush(s) char *s; 
  40. {
  41.  out(s);
  42.  if (substdio_flush(subfdoutsmall) == -1) die();
  43. }
  44. void err(s) char *s;
  45. {
  46.  if (substdio_puts(subfdoutsmall,"-ERR ") == -1) die();
  47.  if (substdio_puts(subfdoutsmall,s) == -1) die();
  48.  if (substdio_puts(subfdoutsmall,"\r\n") == -1) die();
  49.  if (substdio_flush(subfdoutsmall) == -1) die();
  50. }
  51. void die_usage() { err("usage: popup hostname subprogram"); die(); }
  52. void die_nomem() { err("out of memory"); die(); }
  53. void die_pipe() { err("unable to open pipe"); die(); }
  54. void die_write() { err("unable to write pipe"); die(); }
  55. void die_fork() { err("unable to fork"); die(); }
  56. void die_childcrashed() { err("aack, child crashed"); }
  57. void die_badauth() { err("authorization failed"); }
  58.  
  59. void err_syntax() { err("syntax error"); }
  60. void err_wantuser() { err("USER first"); }
  61. void err_authoriz() { err("authorization first"); }
  62.  
  63. void okay() { outflush("+OK \r\n"); }
  64.  
  65.  
  66. char unique[FMT_ULONG + FMT_ULONG + 3];
  67. char *hostname;
  68. stralloc username = {0};
  69. int seenuser = 0;
  70. char **childargs;
  71. substdio ssup;
  72. char upbuf[128];
  73.  
  74.  
  75. void doanddie(user,userlen,pass)
  76. char *user;
  77. unsigned int userlen; /* including 0 byte */
  78. char *pass;
  79. {
  80.  int child;
  81.  int wstat;
  82.  int pi[2];
  83.  int i;
  84.  
  85.  if (fd_copy(2,1) == -1) die_pipe();
  86.  close(3);
  87.  if (pipe(pi) == -1) die_pipe();
  88.  if (pi[0] != 3) die_pipe();
  89.  switch(child = fork())
  90.   {
  91.    case -1:
  92.      die_fork();
  93.    case 0:
  94.      close(pi[1]);
  95.      sig_pipedefault();
  96.      execvp(*childargs,childargs);
  97.      _exit(1);
  98.   }
  99.  close(pi[0]);
  100.  substdio_fdbuf(&ssup,write,pi[1],upbuf,sizeof(upbuf));
  101.  if (substdio_put(&ssup,user,userlen) == -1) die_write();
  102.  if (substdio_put(&ssup,pass,str_len(pass) + 1) == -1) die_write();
  103.  if (substdio_puts(&ssup,"<") == -1) die_write();
  104.  if (substdio_puts(&ssup,unique) == -1) die_write();
  105.  if (substdio_puts(&ssup,hostname) == -1) die_write();
  106.  if (substdio_put(&ssup,">",2) == -1) die_write();
  107.  if (substdio_flush(&ssup) == -1) die_write();
  108.  close(pi[1]);
  109.  for (i = 0;pass[i];++i) pass[i] = 0;
  110.  for (i = 0;i < sizeof(upbuf);++i) upbuf[i] = 0;
  111.  if (wait_pid(&wstat,child) == -1) die();
  112.  if (wait_crashed(wstat)) die_childcrashed();
  113.  if (wait_exitcode(wstat)) die_badauth();
  114.  die();
  115. }
  116. void pop3_greet()
  117. {
  118.  char *s;
  119.  s = unique;
  120.  s += fmt_uint(s,getpid());
  121.  *s++ = '.';
  122.  s += fmt_ulong(s,(unsigned long) now());
  123.  *s++ = '@';
  124.  *s++ = 0;
  125.  
  126.  out("+OK <");
  127.  out(unique);
  128.  out(hostname);
  129.  outflush(">\r\n");
  130. }
  131. void pop3_user(arg) char *arg;
  132. {
  133.  if (!arg) { err_syntax(); return; }
  134.  okay();
  135.  seenuser = 1;
  136.  if (!stralloc_copys(&username,arg)) die_nomem(); 
  137.  if (!stralloc_0(&username)) die_nomem(); 
  138. }
  139. void pop3_pass(arg) char *arg;
  140. {
  141.  if (!seenuser) { err_wantuser(); return; }
  142.  if (!arg) { err_syntax(); return; }
  143.  doanddie(username.s,username.len,arg);
  144. }
  145. void pop3_apop(arg) char *arg;
  146. {
  147.  char *space;
  148.  if (!arg) { err_syntax(); return; }
  149.  space = arg + str_chr(arg,' ');
  150.  if (!*space) { err_syntax(); return; }
  151.  *space++ = 0;
  152.  doanddie(arg,space - arg,space);
  153. }
  154.  
  155. void pop3_quit() { okay(); die(); }
  156.  
  157. static struct { void (*fun)(); char *text; } pop3cmd[] = {
  158.   { pop3_user, "user" }
  159. , { pop3_pass, "pass" }
  160. , { pop3_apop, "apop" }
  161. , { pop3_quit, "quit" }
  162. , { okay, "noop" }
  163. , { 0, 0 }
  164. };
  165.  
  166. void doit(cmd)
  167. char *cmd;
  168. {
  169.  int i;
  170.  int j;
  171.  char ch;
  172.  
  173.  for (i = 0;pop3cmd[i].fun;++i)
  174.   {
  175.    for (j = 0;ch = pop3cmd[i].text[j];++j)
  176.      if ((cmd[j] != ch) && (cmd[j] != ch - 32))
  177.        break;
  178.    if (!ch)
  179.      if (!cmd[j] || (cmd[j] == ' '))
  180.       {
  181.        while (cmd[j] == ' ') ++j;
  182.        if (!cmd[j])
  183.          pop3cmd[i].fun((char *) 0);
  184.        else
  185.          pop3cmd[i].fun(cmd + j);
  186.        return;
  187.       }
  188.   }
  189.  err_authoriz();
  190. }
  191.  
  192. void main(argc,argv)
  193. int argc;
  194. char **argv;
  195. {
  196.  static stralloc cmd = {0};
  197.  int match;
  198.  
  199.  sig_alarmcatch(die);
  200.  sig_pipeignore();
  201.  
  202.  hostname = argv[1];
  203.  if (!hostname) die_usage();
  204.  childargs = argv + 2;
  205.  if (!*childargs) die_usage();
  206.  
  207.  pop3_greet();
  208.  
  209.  for (;;)
  210.   {
  211.    if (getln(&ssin,&cmd,&match,'\n') == -1) die();
  212.    if (!match) die();
  213.    if (cmd.len == 0) die();
  214.    if (cmd.s[--cmd.len] != '\n') die();
  215.    if ((cmd.len > 0) && (cmd.s[cmd.len - 1] == '\r')) --cmd.len;
  216.    cmd.s[cmd.len++] = 0;
  217.    doit(cmd.s);
  218.   }
  219. }
  220.